package com.ruoyi.system.habit.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.ruoyi.common.annotation.DataSource;
import com.ruoyi.common.constant.CurdConstants;
import com.ruoyi.common.constant.HttpStatus;
import com.ruoyi.common.core.domain.WrapperResponse;
import com.ruoyi.common.enums.DataSourceType;
import com.ruoyi.common.exception.ServiceException;
import com.ruoyi.common.exception.UtilException;
import com.ruoyi.common.utils.poi.ExcelUtil;
import com.ruoyi.system.habit.domain.dto.HabitDTO;
import com.ruoyi.system.habit.domain.entity.Habit;
import com.ruoyi.system.habit.mapper.HabitMapper;
import com.ruoyi.system.habit.service.HabitService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.sql.rowset.serial.SerialException;
import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * @author: xujiabing
 * @date: 2024-10-15 10:12
 * @description 打卡习惯serviceImpl
 */
@Slf4j
@Service
@DataSource(DataSourceType.SLAVE)
public class HabitServiceImpl implements HabitService {
    @Autowired
    private HabitMapper habitMapper;

    /**
     * @description: 查询习惯列表
     * @author: xujiabing
     * @date: 2024-10-18 15:42
     * @param: habitDTO
     * @return: PageInfo <Habit>
     */
    @Override
    public PageInfo<Habit> list(HabitDTO habitDTO) {
        //分页
        PageHelper.startPage(habitDTO.getPageNum(), habitDTO.getPageSize());
        LambdaQueryWrapper<Habit> queryWrapper = new LambdaQueryWrapper<>();
        //习惯名称
        queryWrapper.
                eq(StringUtils.isNotEmpty(habitDTO.getName()),
                        Habit::getName, habitDTO.getName());
        //今日是否打卡
        queryWrapper.
                eq(!Objects.isNull(habitDTO.getIsClockToday()),
                        Habit::getIsClockToday, habitDTO.getIsClockToday());

        List<Habit> list = habitMapper.selectList(queryWrapper);

        return new PageInfo<>(list);
    }

    /**
     * @description: 新增习惯
     * @author: xujiabing
     * @date: 2024-10-19 22:47
     * @param: habitDTO
     * @return:
     */
    @Override
    public void add(HabitDTO habitDTO) {
        if (Objects.isNull(habitDTO)) {
            throw new ServiceException("入参为 null");
        }
        Habit habit = new Habit();
        //拷贝数据
        BeanUtils.copyProperties(habitDTO, habit);
        habit.setCreateTime(new Date());
        int insert = habitMapper.insert(habit);
        if (insert <= 0) {
            throw new ServiceException(CurdConstants.INSERT_ERROR);
        }
    }

    /**
     * @description: 修改习惯
     * @author: xujiabing
     * @date: 2024-10-20 14:37
     * @param: habitDTO
     * @return:
     */
    @Override
    public void edit(HabitDTO habitDTO) {
        if (Objects.isNull(habitDTO.getId())) {
            throw new ServiceException("id为 null");
        }
        Habit habit = new Habit();
        //拷贝数据
        BeanUtils.copyProperties(habitDTO, habit);
        int update = habitMapper.updateById(habit);
        if (update <= 0) {
            throw new ServiceException(CurdConstants.UPDATE_ERROR);
        }
    }

    /**
     * @description: 删除习惯, 可批量
     * @author: xujiabing
     * @date: 2024-10-20 14:42
     * @param: ids
     * @return:
     */
    @Override
    public void removeByIds(List<Integer> ids) {
        if (ids.isEmpty()) {
            throw new ServiceException("ids 集合为 null");
        }
        int batchIds = habitMapper.deleteBatchIds(ids);
        if (batchIds <= 0) {
            throw new ServiceException(CurdConstants.REMOVE_ERROR);
        }
    }

    /**
     * @description: 查询习惯, 根据id
     * @author: xujiabing
     * @date: 2024-10-20 15:43
     * @param: id
     * @return: Habit
     */
    @Override
    public Habit queryById(Integer id) {
        if (Objects.isNull(id)) {
            throw new ServiceException("id 为 null");
        }
        return habitMapper.selectById(id);
    }

    /**
     * @description: 导出查询
     * @author: xujiabing
     * @date: 2024-10-20 17:23
     * @param: habitDTO
     * @return: List<Habit>
     */
    @Override
    public List<Habit> queryByExport(HabitDTO habitDTO) {
        LambdaQueryWrapper<Habit> queryWrapper = new LambdaQueryWrapper<>();
        //习惯名称
        queryWrapper.
                eq(StringUtils.isNotEmpty(habitDTO.getName()),
                        Habit::getName, habitDTO.getName());
        //今日是否打卡
        queryWrapper.
                eq(!Objects.isNull(habitDTO.getIsClockToday()),
                        Habit::getIsClockToday, habitDTO.getIsClockToday());

        return habitMapper.selectList(queryWrapper);
    }

    /**
     * @description: 导入excel
     * @author: xujiabing
     * @date: 2024-10-30 20:32
     * @param: file
     * @param: updateFlag true 更新已存在
     * @return: String
     */
    @Override
    public String imports(MultipartFile file, Boolean updateFlag) {
        ExcelUtil<Habit> excelUtil = new ExcelUtil<>(Habit.class);
        //返回数据
        int successNum = 0;
        int failureNum = 0;
        StringBuilder successMsg = new StringBuilder();
        StringBuilder failureMsg = new StringBuilder();

        List<Habit> list = null;
        try {
            list = excelUtil.importExcel(file.getInputStream());//转换成集合
        } catch (IOException e) {
            throw new UtilException(e);
        }
        if (list.isEmpty()) {
            throw new ServiceException("导入数据为空");
        }
        for (Habit habit : list) {
            try {
                //校验是否存在
                LambdaQueryWrapper<Habit> wrapper = new LambdaQueryWrapper<>();
                //判断 习惯的uid和名称组合 是否唯一
                wrapper.eq(Habit::getUid, habit.getUid());
                wrapper.eq(Habit::getName, habit.getName());
                Habit selectOne = habitMapper.selectOne(wrapper);
                if (Objects.isNull(selectOne)) {
                    //不存在,新增
                    this.habitMapper.insert(habit);
                    successNum++;
                    successMsg.append("<br/>" + successNum + "、习惯:" + habit.getName() + " 新增成功");
                } else {//存在
                    if (updateFlag) {//存在且更新
                        LambdaUpdateWrapper<Habit> updateWrapper = new LambdaUpdateWrapper<Habit>()
                                .eq(Habit::getName, habit.getName())
                                .eq(Habit::getUid, habit.getUid());
                        //修改
                        habitMapper.update(habit, updateWrapper);
                        successNum++;
                        successMsg.append("<br/>" + successNum + "、习惯:" + habit.getName() + " 更新成功");
                    } else {//存在不更新
                        failureNum++;
                        failureMsg.append("<br/>" + failureNum + "、习惯:" + habit.getName() + " 已存在");
                    }
                }
            } catch (Exception e) {
                failureNum++;
                failureMsg.append("<br/>" + failureNum + "、习惯:" + habit.getName() + " 已存在");
                throw new RuntimeException(e);
            }

        }
        //导入统计
        if (list.size() == successNum) {//全部导入成功
            successMsg.insert(0, "恭喜您，数据已全部导入成功！共 " + successNum + " 条，数据如下：");
            return successMsg.toString();
        }

        if (list.size() == failureNum) {//全部导入失败
            failureMsg.insert(0, "很抱歉，数据全部导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            return failureMsg.toString();
        }
        StringBuilder stringBuilder = new StringBuilder();
        if (successNum > 0 && failureNum > 0) {//既有成功有有失败
            failureMsg.insert(0, "<br/>" + "数据导入失败！共 " + failureNum + " 条数据格式不正确，错误如下：");
            successMsg.insert(0, "<br/>" + "数据导入成功！共 " + successNum + " 条，数据如下：");
            stringBuilder.append(successMsg);
            stringBuilder.append(failureMsg);
        }
        return stringBuilder.toString();
    }
}
